/*---------------------------------------------------------------------------*\
  =========                 |
  \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
   \\    /   O peration     |
    \\  /    A nd           | www.openfoam.com
     \\/     M anipulation  |
-------------------------------------------------------------------------------
    Copyright (C) 2015 OpenFOAM Foundation
    Copyright (C) 2018 OpenCFD Ltd.
-------------------------------------------------------------------------------
License
    This file is part of OpenFOAM.

    OpenFOAM is free software: you can redistribute it and/or modify it
    under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
    ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
    FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
    for more details.

    You should have received a copy of the GNU General Public License
    along with OpenFOAM.  If not, see <http://www.gnu.org/licenses/>.

Class
    Foam::radiation::solarLoad

Group
    grpRadiationModels

Description
    The solar load radiation model includes Sun primary hits, their
    reflective fluxes and diffusive sky radiative fluxes.

    The primary hit rays are calculated using a face shading algorithm.
    The first reflected fluxes can be optionally included. A view factors
    method is needed in order to include diffusive surface to surface fluxes.

    The energy is included on "visible" walls by default. The sky diffusive
    radiation for horizontal and vertical walls is calculated following the
    Fair Weather Conditions Method from the ASHRAE Handbook.

    By default the energy is included in cells adjacent to the patches into
    the energy Equation (wallCoupled = false). On coupled patches the flux is
    by default added to the wall and considered into the solid
    (solidCoupled = true).

    The solarLoad model can be used in conjuntion with fvDOM and viewFactor
    radiation models. The flag useSolarLoad must be true on the rediation
    dictionary.


SourceFiles
    solarLoad.C

\*---------------------------------------------------------------------------*/

#ifndef radiation_solarLoad_H
#define radiation_solarLoad_H

#include "radiationModel.H"
#include "volFields.H"
#include "faceShading.H"
#include "faceReflecting.H"
#include "solarCalculator.H"

// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //

namespace Foam
{
namespace radiation
{

/*---------------------------------------------------------------------------*\
                           Class solarLoad Declaration
\*---------------------------------------------------------------------------*/

class solarLoad
:
    public radiationModel
{

private:

    // Private data

        //- Dictionary
        dictionary dict_;

        //- Net radiative heat flux [W/m2]
        volScalarField qr_;

        //- Direct hit faces Ids
        autoPtr<faceShading> hitFaces_;

        //- Reflected faces
        autoPtr<faceReflecting> reflectedFaces_;

        //- Source term for cells next to patches with flags solidCoupled
        //- and wallCoupled false
        DimensionedField<scalar, volMesh> Ru_;

        //- Solar calculator
        solarCalculator solarCalc_;

        //- Vertical direction (Default is g vector)
        vector verticalDir_;

        //- Include reflected rays from specular surfaces
        bool useReflectedRays_;

        //- Spectral distribution for the integrated solar heat flux
        scalarList spectralDistribution_;

        //-Number of bands
        label nBands_;

        //- Primary solar radiative heat flux per band [W/m2]
        PtrList<volScalarField> qprimaryRad_;

        //- Couple solids through mapped boundary patch using qr (default:true)
        bool solidCoupled_;

        //- Couple wall patches using qr (default:false)
        bool wallCoupled_;

        //- Absorptivity list
        List<List<tmp<scalarField>>> absorptivity_;

        //- Update absorptivity
        bool updateAbsorptivity_;

        //- First iteration
        bool firstIter_;

        //- Update Sun position index
        label updateTimeIndex_;


    // Private Member Functions

        //- Initialise
        void initialise(const dictionary&);

        //- Update direct hit faces radiation
        void updateDirectHitRadiation(const labelList&, const labelHashSet&);

        //- Update reflected heat flux
        void updateReflectedRays(const labelHashSet&);

        //- Calculate diffusive heat flux
        //void calculateQdiff(const labelHashSet&, const labelHashSet&);

        //- Update Sky diffusive radiation
        void updateSkyDiffusiveRadiation
        (
            const labelHashSet&,
            const labelHashSet&
        );

        //- Update hit faces
        bool updateHitFaces();

        //- Update absorptivity
        void updateAbsorptivity(const labelHashSet& includePatches);

        //- No copy construct
        solarLoad(const solarLoad&) = delete;

        //- No copy assignment
        void operator=(const solarLoad&) = delete;


public:

    //- Runtime type information
    TypeName("solarLoad");


    // Constructors

        //- Construct from volScalarField
        solarLoad(const volScalarField& T);

        //- Construct from dictionary and volScalarField
        solarLoad(const dictionary& dict, const volScalarField& T);


    //- Destructor
    virtual ~solarLoad() = default;


    // Member functions

        // Edit

            //- Solve
            void calculate();

            //- Read radiation properties dictionary
            bool read();

            //- Source term component (for power of T^4)
            virtual tmp<volScalarField> Rp() const;

            //- Source term component (constant)
            virtual tmp<DimensionedField<scalar, volMesh>> Ru() const;


    // Access

        //- Number of bands
        label nBands() const;

        //- Primary solar heat flux
        const volScalarField& qprimaryRad(const label bandI) const
        {
            return qprimaryRad_[bandI];
        }
};


// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //

} // End namespace radiation
} // End namespace Foam

// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //

#endif

// ************************************************************************* //
